package marble.views {

	import flash.events.MouseEvent;
	
	import marble.Facade;
	import marble.model.Element;
	import marble.model.PlanProxy;
	
	import mx.containers.HBox;
	import mx.containers.VBox;
	import mx.controls.Label;
	import mx.events.FlexEvent;
	import mx.rpc.events.ResultEvent;
	
	/**
	 * This view is presented to any non-logged user.
	 * It is then  read-only  and shows the  overall
	 * publicly available conference plan.  
	 */
	public class DefaultViewClass extends VBox {

		public static const EMPTY_STATE:String = "state_defaultView_emptyPlan";

		[Bindable]
		public var pageArrows:HBox;
		public var info:Label;
	
		[Bindable]
		protected var facade:Facade = Facade.getInstance();

		private var elements:Array = new Array();
		protected var plan:PlanProxy;

		protected var minTime:int;
		protected var maxTime:int;

		private var minDate:Date = new Date(1111111111111111);
		private var maxDate:Date = new Date(0);

		private var firstMonday:Date;
		private var first:Element;
		
		[Bindable]
		public var numWeeks:Number;
		private var numDays:Number;
		
		[Bindable]
		public var currentPage:int;
		
		public function DefaultViewClass() {
			super();
			addEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete);
		}
		
		protected function onCreationComplete(event:FlexEvent):void {
			facade.callRemote("getPlanElementsList", [], getElementsListHandler);
		}
		
		public function onNextPage(event:MouseEvent):void {
			currentPage = (currentPage + 1) % numWeeks;
			updatePlan();
		}
		
		public function onPrevPage(event:MouseEvent):void {
			if (currentPage == 0) {
				currentPage = numWeeks - 1;
			} else {
				currentPage--;
			}
			updatePlan();
		}
		
		protected function updatePlan(addRem:Boolean = false, reg:Boolean = false):void {
			if (plan != null) {
				removeChild(plan);
			}
			plan = new PlanProxy(
				pagedElements(),
				getPageMonday(),
				minTime, maxTime,
				addRem, reg,
				null
			);
			plan.width = 900;
			addChild(plan);
		}

		protected function getElementsListHandler(event:ResultEvent):void {

			for each (var obj:Object in event.result) {

				var el:Element = Element.create(obj);
				elements.push(el);

				var actualDate:Date = el.getDate();

				if (actualDate.getTime() < minDate.getTime()) {
					minDate = actualDate;
					first = el;
				}

				if (actualDate.getTime() > maxDate.getTime()) {
					maxDate = actualDate;
				}
			}
			
			if (elements.length > 0) {

				currentState = "";

				firstMonday = new Date(minDate);
				firstMonday.date -= first.getDayOfWeek();
				firstMonday.hours = 0;
				firstMonday.minutes = 0;
				firstMonday.seconds = 0;
				firstMonday.milliseconds = 0;

				numDays = Math.ceil((maxDate.getTime() - firstMonday.getTime()) / 86400000);
				numWeeks = Math.max(1, Math.ceil(numDays / 7));

				pageArrows.visible = true;
				updatePlan();
			} else {
				currentState = EMPTY_STATE;
				info.text = facade.locale.translate(
					"There are no elements in the conference schedule."
				);
			}
		}

		protected function getPageMonday():Date {
			var dayOffset:int = currentPage * 7;
			var start:Number = firstMonday.getTime() + (dayOffset * 86400000);
			return new Date(start);
		}

		protected function pagedElements():Array {

			var dayOffset:int = currentPage * 7;
			var start:Number = firstMonday.getTime() + (dayOffset * 86400000);
			var end:Number = start + (7 * 86400000);

			minTime = int.MAX_VALUE;
			maxTime = 0;

			var filtered:Array = new Array();
			for each (var el:Element in elements) {
				var t:Number = el.getDate().getTime();
				if (t >= start && t <= end) {

					filtered.push(el);

					var actualTime:int = el.timeMinutes;
					
					if (actualTime < minTime) {
						minTime = actualTime;
					}

					if (actualTime + el.duration > maxTime) {
						maxTime = actualTime + el.duration;
					}
				} 
			}

			// round to multiples of 60 min
			minTime = Math.floor(minTime / 60) * 60;
			maxTime = Math.ceil(maxTime / 60) * 60;

			// provide minimal time span (14 hrs)
			var diff:int = maxTime - minTime;
			if (diff < 840) {

				minTime = minTime - Math.floor((840 - diff) / 2); 
				maxTime = maxTime + Math.ceil((840 - diff) / 2);

				if (minTime % 60 != 0) {
					minTime += 30;
				}

				if (maxTime % 60 != 0) {
					maxTime += 30;
				}		
			}

			return filtered;
		}
	}
}